#ifndef xpack_graphic_draw_rectanglehv
#define xpack_graphic_draw_rectanglehv
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::graphic_draw_rectanglehv::inc
#include"define/base_type.hpp"
#include"macro/xexport.hpp"
#include"graphic/draw/lineh.hpp"
#include"graphic/draw/linev.hpp"
#include"graphic/private/rander_helper.hpp"
#include"graphic/rander_wrapper.hpp"
#include"macro/xalways_inline.hpp"
#include"math/point.hpp"
#pragma pop_macro("xuser")

namespace mixc::graphic_draw_rectanglehv::inc{
    template<class rander_t>
    inline void xalways_inline rectanglehv_core(
        inc::pt2wx          start, 
        uxx                 width_of_left_to_right,
        uxx                 height_of_bottom_to_top,
        rander_t    const & rander
    ){
        if (height_of_bottom_to_top <= 1){
            return inc::draw::lineh(start, width_of_left_to_right, rander);
        }
        if (width_of_left_to_right <= 1){
            return inc::draw::linev(start, height_of_bottom_to_top, rander);
        }

        // 取消 keep_context() ，因为影响性能
        auto thichness_mode     = inc::rander_helper::get_thickness_mode(rander);
        inc::rander_helper::set_thickness_mode(rander, inc::thickness_mode_t::become_thick);
        inc::draw::lineh(start, width_of_left_to_right, [&](auto x, auto y){
            rander(x, y);
            rander(x, y + height_of_bottom_to_top - 1);
        });

        inc::rander_helper::set_thickness_mode(rander, inc::thickness_mode_t::become_wider);
        inc::draw::linev(start, height_of_bottom_to_top, [&](auto x, auto y){
            rander(x, y);
            rander(x + width_of_left_to_right - 1, y);
        });

        // 还原
        inc::rander_helper::set_thickness_mode(rander, thichness_mode);
    }
}

namespace mixc::graphic_draw_rectanglehv::origin{
    template<class rander_t>
    inline void xalways_inline rectanglehv(
        inc::pt2wx          start, 
        uxx                 width_of_left_to_right,
        uxx                 height_of_bottom_to_top,
        rander_t    const & rander
    ){
        if (auto thickness = inc::rander_helper::get_thickness(rander); thickness > 1){
            inc::rander_helper::thickening(rander, [&](auto const & outside_rander, auto const & inside_rander){
                auto plus           = ixx(thickness) - 1;
                auto outside_start  = start(-plus, -plus);
                auto outside_width  = width_of_left_to_right + plus * 2;
                auto outside_height = height_of_bottom_to_top + plus * 2;
                inc::rectanglehv_core(outside_start, outside_width, outside_height, outside_rander);
                inc::rectanglehv_core(start, width_of_left_to_right, height_of_bottom_to_top, inside_rander);
            });
        }
        else{
            inc::rectanglehv_core(start, width_of_left_to_right, height_of_bottom_to_top, rander);
        }

        // 注意:
        // 使用显式 texturing 而非通用 texturing 以便能有更好的性能
        if constexpr (inc::is_rander_wrapper<rander_t>){
            if (inc::rander_helper::get_texture_mode(rander) == inc::texture_mode_t::none){
                return;
            }

            // 无需考虑 height_of_bottom_to_top <= 2 的情况，linev() 内部使用 ixx 判断
            // xlikely(height_of_bottom_to_top > 2){
            // }
            //
            // 由于 start(1, 1) 向右上各自移动一个单位，不能画到上边框，所以是减 2 不是减 1
            inc::draw::linev(start(1, 1), height_of_bottom_to_top - 2, [&](auto x, auto y){
                rander.texturing(x, y, width_of_left_to_right - 2);
            });
        }
    }

    template<class rander_t>
    inline void xalways_inline rectanglehv(
        uxx                 width_of_left_to_right,
        uxx                 height_of_bottom_to_top,
        rander_t    const & rander
    ){
        rectanglehv({}, width_of_left_to_right, height_of_bottom_to_top, rander);
    }
}
#endif

xexport_spacex(draw, mixc::graphic_draw_rectanglehv::origin)
